#include "sdopencv/PHaarFeatureSet.hpp"

using namespace std;
using namespace sdopencv;

PHaarFeatureSet *generate_set_PHaar_all(int patch_len)
{
    PHaarFeatureSet *z = new PHaarFeatureSet();
    vector<int> params;
    params.resize(3);

    PHaarFeature hf;
    CvSize sz;


    for(int type_index = 0; type_index < 8; ++type_index)
    {
        AbstractPHaarType *ht = new_PHaarType(type_index);

        for(int to_swap = 0; to_swap <= ht->can_swap; ++to_swap)
            for(int to_rotate90 = 0; to_rotate90 <= ht->can_rotate90; ++to_rotate90)
                for(int to_rotate180 = 0; to_rotate180 <= ht->can_rotate180; ++to_rotate180)
                    for(params[0] = 0; params[0] < patch_len; ++params[0])
                        for(params[1] = 0; params[1] < patch_len; ++params[1])
                            for(params[2] = 0; params[2] < patch_len; ++params[2])
        {
            sz = ht->size(params);
            if(sz.width < 0 || patch_len - sz.width < 2 || patch_len - sz.height < 2) continue;

            for(int x = 1; x < patch_len - sz.width; ++x)
                for(int y = 1; y < patch_len - sz.height; ++y)
            {
                hf = ht->generate(x, y, params);
                if(to_swap) hf = hf.swap();
                if(to_rotate90) hf = hf.rotate90(patch_len);
                if(to_rotate180) hf = hf.rotate180(patch_len);

                z->push_back(hf);
            }

            if(ht->nparams < 3) break;
        }

        delete ht;
    }

    return z;
}


istream& operator >>(istream &is, PHaarFeatureSet &obj)
{
    int n, i;
    is >> n;
    obj.resize(n);
    for(i = 0; i < n; ++i)
        is >> obj[i];
    return is;
}


ostream& operator <<(ostream &os, const PHaarFeatureSet &obj)
{
    os << obj.size() << endl << endl;
    for(int i = 0; i < obj.size(); ++i)
        os << obj[i] << endl;
    os << endl;
    return os;
}


// project N square patches (uchar 1 channel) of length patch_len down to 1D using a subset of features
// src is a continuous byte array of shape(N, patch_len, patch_len) i.e. patch_len should be divisible by 4
// dst is a continuous double array of shape (N, M) to store the projected values, where M=indices.size()
void project(unsigned char *src, double *dst, int N, int patch_len, PHaarFeatureSet *hfs, const vector<int> &indices)
{
    int i, n;
    PolygonalIntegrator polyint(patch_len, patch_len, 2);
    IplImage img;
    cvInitImageHeader(&img, cvSize(patch_len, patch_len), IPL_DEPTH_8U, 1);
    PHaarFeature *hf;

    double *ddst;

    ddst = dst;
    for(n = 0; n < N; ++n)
    {
        cvSetData(&img, src+n*patch_len*patch_len, patch_len);
        polyint.input_image(&img);

        for(i = 0; i < indices.size(); ++i)
        {
            hf = &(*hfs)[indices[i]];
            *(ddst++) = polyint.integrate(hf->p[1])/hf->A[1] + polyint.integrate(hf->p[0])/hf->A[0];
        }
    }
}


